#include "include.h"

/* Frame retrieved from swapfile. Synchronously update PTE with frame_num */
int sos_page_swapin(sos_pcb *pcb, seL4_Word proc_vaddr, seL4_Word frame_num) {
    int err;
    page_table_entry *pte;

    if (pcb->abort) {
        frame_free(frame_translate_number(frame_num));
        return SOS_PAGE_TABLE_ABORT;
    }

    // Walk the page table
    err = page_walk_nofault(pcb, proc_vaddr, &pte);
    if (err != SOS_PAGE_TABLE_SUCCESS) {
        // Fundamental assumption has been broken. Somehow, our page table has
        // been damaged, or this request is erroneous.
        conditional_panic(err, "page_swapin: page walk failed unexpectedly");
        return SOS_PAGE_TABLE_INVAL;
    }

    // Update PTE
    pte->attrs.swapped = 0;
    pte->framenumber = frame_num;
    return SOS_PAGE_TABLE_SUCCESS;
}

/* Frame is being evicted. Synchronously update PTE with swap_num */
int sos_page_swapout(sos_pcb *pcb, seL4_Word proc_vaddr, seL4_Word swap_num) {
    int err;
    page_table_entry *pte;

    if (pcb->abort) {
        sos_swap_free(swap_num);
        return SOS_PAGE_TABLE_ABORT;
    }

    dprintf(5, "sos_page_swapout: pcb %p\tproc_vaddr %p\tswap_num %p\n",
            pcb, proc_vaddr, swap_num);

    // Walk the page table
    err = page_walk_nofault(pcb, proc_vaddr, &pte);
    if (err != SOS_PAGE_TABLE_SUCCESS) {
        // Attempt to swap out a page that's never been faulted or mapped!
        conditional_panic(err, "page_swapout: page walk failed unexpectedly");
        return SOS_PAGE_TABLE_INVAL;
    }

    // Update PTE
    dprintf(6, "sos_page_swapout: updating attributes / swap number\n");
    pte->attrs.swapped = 1;
    pte->framenumber = swap_num;

    dprintf(6, "sos_page_swapout: done\n");
    return SOS_PAGE_TABLE_SUCCESS;
}
